package threadedSimulator;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JList;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import Processes.ComputeBoundProcess;
import Processes.ConsumerProcess;
import Processes.Processes;
import Processes.ProducerProcess;
import Schedulers.Scheduler;

//executes the currently running simulated 
//process and handles low-level OS tasks

//The CPU will need, at a minimum, a PC (program 
//counter) that records the address of the instruction currently being 
//executed within the currently running process. When each 
//instruction finishes, the PC is incremented, modulo the instruction 
//size of the process, thus all processes will execute indefinitely
//The CPU must handle interrupts, which are generated by I/O 
//devices. When an interrupt occurs, the PC will need to be stored in 
//the interrupted process' PCB (this is part of a context switch) and 
//the CPU must then handle the interrupt. For example, if a keyboard 
//device produced an interrupt (signaling that the user typed a key) a 
//process that was waiting for keyboard input, via a system call, may 
//have its state changed from blocked to runnable. 

/**
 * 
 * @author
 * @version 3/11/2014
 */
public class Cpu implements Runnable, ActionListener {

	Scheduler my_scheduler;
	Timer my_timer;
	JList<String> my_output;
	List<String> my_output_list = new LinkedList<String>();
    String my_outputcause;
    int my_numberof_computebound = 0;
    int my_numberof_consumer = 0;
	private JScrollPane my_scroll; 
	
	/**
	 * @param my_panel 
	 * 
	 */
	public Cpu(JList<String> the_panel, String the_numberof_computebound, String the_numberof_consumer) {
//		my_scheduler = the_scheduler;
		my_timer = new Timer(this);
		my_timer.start();
		my_output = the_panel;
		my_numberof_computebound = Integer.parseInt(the_numberof_computebound);
		my_numberof_consumer = Integer.parseInt(the_numberof_consumer);
	}
	
	public void addScheduler(Scheduler the_scheduler)
	{
//		System.out.println(the_scheduler.getClass());
		my_scheduler = the_scheduler;
		for(int x = 0; x < my_numberof_computebound; x++)
		{
			my_scheduler.addProcess(new ComputeBoundProcess(this, ""));
		}
		for(int x = 0; x < my_numberof_consumer; x++)
		{
			my_scheduler.addProcess(new ConsumerProcess(this, ""));
		}
	}

	/**
	 * 
	 */
	@Override
	public void run() {
		// TODO Auto-generated method stub
	}

	public void addProcess(Processes the_processes)
	{
//		System.out.println("added process");
		my_scheduler.addProcess(the_processes);
	}
	
	/**
	 * 
	 * @param the_interuptor
	 */
	public boolean interupt(final Processes the_interuptor) {
		return my_scheduler.systemCall(the_interuptor);
	}
	
	public void pause()
	{
		if (my_timer.isPaused()) {
			my_timer = new Timer(this);
			my_timer.start();
		} else {
			my_timer.stop();		
		}
	}

	@Override
	public void actionPerformed(ActionEvent the_e) {
		my_scheduler.quantumStep();
	}
	
	public void addToOutput(String the_string, String cause_of)
	{
		String lines[] = the_string.split("\n");
		String[] array = new String[my_output_list.size() + lines.length+1];
        for (int i = 0; i < my_output_list.size(); i++) {
        	array[i] = my_output_list.get(i);
        }
        int place = my_output_list.size();
        for (int i = 0; i < lines.length; i++) {
        	array[i + place] = lines[i];
        	my_output_list.add(lines[i]);
        }
        my_output_list.add(cause_of + " made an interupt.");
		my_output.setListData(array);
		
		JScrollBar vertical = my_scroll.getVerticalScrollBar();
		vertical.setValue(vertical.getMaximum()); 
	}
	
	public void setScroll(JScrollPane the_scroll)
	{
		my_scroll = the_scroll;
	}
	
	public void pauseFor(int delay, String cause_of_delay)
	{
		my_output_list.add(cause_of_delay + " made an interupt.");
		String[] array = new String[my_output_list.size()];
        for (int i = 0; i < my_output_list.size(); i++) {
        	array[i] = my_output_list.get(i);
        }
		my_output.setListData(array);
		
		JScrollBar vertical = my_scroll.getVerticalScrollBar();
		vertical.setValue(vertical.getMaximum()); 
		my_timer.stop();
		my_timer = new Timer(this, delay);
		my_timer.start();
	}

}
